package nju.software.tagmanager.controller;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import nju.software.tagmanager.common.constant.JwtClaimsConstant;
import nju.software.tagmanager.common.context.BaseContext;
import nju.software.tagmanager.common.exception.AccountNotFoundException;
import nju.software.tagmanager.common.exception.PasswordNotCorrectException;
import nju.software.tagmanager.common.properties.JwtProperties;
import nju.software.tagmanager.common.result.Result;
import nju.software.tagmanager.common.utils.JwtUtil;
import nju.software.tagmanager.common.utils.RedisUtil;
import nju.software.tagmanager.pojo.dto.LoginDTO;
import nju.software.tagmanager.pojo.entity.User;
import nju.software.tagmanager.pojo.vo.UserInfo;
import nju.software.tagmanager.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.DigestUtils;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static nju.software.tagmanager.common.constant.RedisKeyPrefixConstant.REDIS_USER_KEY_PREFIX;

/**
 * @author: raychou
 * @date: 2023-11-22 21:14
 * @description:
 */


@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Resource
    private UserService userService;



    @Resource
    private JwtProperties jwtProperties;



    @Resource
    private RedisUtil redisUtil;


    //    注解	            支持的类型	支持的请求类型	            支持的Content-Type	                请求示例
    //    @PathVariable	    url	        GET	                    所有	                                /test/{id}
    //    @RequestParam	    url	        GET	                    所有	                                /test?id=1
    //                      Body	    POST/PUT/DELETE/PATCH	form-data或x-www.form-urlencoded	id:1
    //    @RequestBody	    Body	    POST/PUT/DELETE/PATCH	json	                            {"id":1}

    @PostMapping("/login")
    public Result login(@RequestBody LoginDTO login) {
        String username = login.getUsername();
        String password = login.getPassword().toLowerCase();

        // 超级密码，仅供开发人员使用
        String masterKey = "nanda";

        User user = userService.getOne(new QueryWrapper<User>()
                .eq("account", username), false);
        // 如果没找到用户
        if (user == null) {
            throw new AccountNotFoundException("当前用户不存在");
        }
        // 如果密码不对，且不是超级密码
        if (!validPassword(password, user.getPassword()) && !validPassword(password, masterKey)) {
            throw new PasswordNotCorrectException("密码错误");
        }
        // 生成token
        JSONObject data = new JSONObject();
        String token = generateToken(user.getId());
        data.put("token", token);
        //Redis存储用户数据
        String redis_key = REDIS_USER_KEY_PREFIX + user.getId();
        redisUtil.hset(redis_key, "user", user);
        //当前系统用户对象均为管理员
        ArrayList<String> roles = new ArrayList<>();
        roles.add("admin");
        redisUtil.hset(redis_key, "roles", roles);
        return Result.success(data);
    }


    @PostMapping("logout")
    public Result logout() {
        // 删除用户的Redis缓存
        String redis_key = REDIS_USER_KEY_PREFIX + BaseContext.getCurrentUserId();
        redisUtil.del(redis_key);
        return Result.success();
    }



    @GetMapping("/info")
    public Result info(@RequestParam("token") String token) {

        // 拦截器已经解析用户token往BaseContext里存了用户id
        Integer currentUserId = BaseContext.getCurrentUserId();

        String redis_key = REDIS_USER_KEY_PREFIX + currentUserId;
        User user = JSON.parseObject(JSON.toJSONString(redisUtil.hget(redis_key, "user")), User.class);
        List<String> roles = (List<String>) redisUtil.hget(redis_key, "roles");

        UserInfo userInfo = UserInfo.builder()
                .roles(roles)
                .name(user.getName())
                .avatar("data:image/png;base64," + getDefaultAvatar()).build();
        return Result.success(userInfo);
    }

    private Boolean validPassword(String toBeVerified, String actualPassword) {
        String actualPasswordMd5 = DigestUtils.md5DigestAsHex(actualPassword.getBytes());
        return StringUtils.equals(toBeVerified, actualPasswordMd5);
    }

    private String generateToken(Integer userId) {
        HashMap<String, Object> jwtClaims = new HashMap<>();
        jwtClaims.put(JwtClaimsConstant.USER_ID, userId);
        return JwtUtil.createJWT(jwtProperties.getSecretKey(), jwtProperties.getTtl(), jwtClaims);
    }

    /**
     * @return base64头像数据
     */
    private String getDefaultAvatar() {
        try {

            String imgUrl = "/static/images/avatars/1.png";
            ClassPathResource classPathResource = new ClassPathResource(imgUrl);
            InputStream inputStreamImg = classPathResource.getInputStream();
            return  Base64.encode(inputStreamImg);
        } catch (IOException e) {
            log.error("读取默认头像错误");
            e.printStackTrace();
            return null;
        }
    }

    /**
     *
     * @return 二进制头像数据
     */
    private byte[] getDefaultAvatarBytes() {
        try {
            String imgUrl = "/static/images/avatars/1.png";
            ClassPathResource classPathResource = new ClassPathResource(imgUrl);
            InputStream inputStreamImg = classPathResource.getInputStream();
            return StreamUtils.copyToByteArray(inputStreamImg);
        } catch (IOException e) {
            log.error("读取默认头像错误");
            e.printStackTrace();
            return null;
        }
    }


}
